﻿using System.Diagnostics;

using DanielVaughan;
using DanielVaughan.ComponentModel.StatePreservation;
using DanielVaughan.Concurrency;
using DanielVaughan.InversionOfControl;
using DanielVaughan.InversionOfControl.Containers.SimpleContainer;
using DanielVaughan.Messaging;
using DanielVaughan.NavigationModel;
using DanielVaughan.PhoneTasks;
using DanielVaughan.Services;
using DanielVaughan.Services.Implementation;
using DanielVaughan.UserOptionsModel;

namespace CalciumTemplateApp
{
	/// <summary>
	/// This class initializes various key services. 
	/// Type registrations occur based on the build configuration.
	/// </summary>
	public class Bootstrapper
	{
		readonly StateManager stateManager = new StateManager();
		readonly NavigationMonitor navigationMonitor = new NavigationMonitor();

		public void Run()
		{
			InitializeContainer();
			/* The state manager performs automatic persistence of properties 
			 * when the app is tombstoned or terminated. 
			 * See the PersistencyExampleViewModel. */
			stateManager.Initialize();
			/* The navigation monitor lets the app's viewmodels know when 
			 * a page transition occurs, and allows the viewmodel 
			 * to cancel the navigation. 
			 * The ViewModelBase class contains the current query string. */
			navigationMonitor.Initialize();
		}

		/// <summary>
		/// Initializes the IoC container by registering type associations 
		/// and singleton instances.
		/// </summary>
		void InitializeContainer()
		{
			/* Simple container is the Calcium IoC container that works with Windows Phone. 
			 * It supports both inversion of control and dependency injection. 
			 * It can be accessed globally using the Dependency class. 
			 * The Dependency class leverages the Microsoft ServiceLocator, 
			 * allowing you to change the IoC container implementation. */
			SimpleContainer container = new SimpleContainer();
			container.InitializeServiceLocator();
			
			/* The following are type associations applicable 
			 * to both build configurations. */

			Dependency.Register<ISettingsService, SettingsService>(true);

			MessageService messageService 
				= new MessageService
			        {
						/* Lambda expressions are used to retrieve the default message service captions, 
						 * which allows the language to be changed at run-time. */
			            DefaultMessageCaptionFunc = () => MainResources.MessageService_DefaultMessageCaption,
						DefaultQuestionCaptionFunc = () => MainResources.MessageService_DefaultQuestionCaption,
						DefaultWarningCaptionFunc = () => MainResources.MessageService_DefaultWarningCaption,
						DefaultErrorCaptionFunc = () => MainResources.MessageService_DefaultErrorCaption,
			        };
			Dependency.Register<IMessageService>(messageService);

			Dependency.Register<IProvider<ISynchronizationContext>, UIContextProvider>();
			Dependency.Register<IMessageBus, MessageBus>(true);
			Dependency.Register<INavigationService, FrameNavigationService>(true);
			Dependency.Register<IUserOptionsService, UserOptionsService>(true);

			AppSettings.InitializeUserOptions();

			/* Build configuration specific associations. */
#if DEBUG
			RegisterDebugTypes();
#else
			RegisterReleaseTypes();
#endif
		}

		/// <summary>
		/// Registers the debug types. 
		/// Mock types are used for types that cause the app to be deactivated.
		/// </summary>
		void RegisterDebugTypes()
		{
			Dependency.Register<IMarketplaceService>(new MockMarketplaceService { Trial = true });
			Dependency.Register<IMarketplaceDetailTask>(new MockMarketplaceDetailTask());
		}

		/// <summary>
		/// Registers the release types. 
		/// Since the app will fail marketplace certification if the assembly 
		/// is built using a debug configuration, the release configuration 
		/// guarantees that no mock type registrations will make it into a published app.
		/// </summary>
		void RegisterReleaseTypes()
		{
			Dependency.Register<IMarketplaceService, MarketplaceService>();
			Dependency.Register<IMarketplaceDetailTask, MarketplaceDetailTaskAdapter>();
		}
	}
}
